package com.roamer.audition.server.service;

import com.roamer.audition.common.request.CompanyDTO;
import com.roamer.audition.common.request.CompanyPageQuery;
import com.roamer.audition.common.request.CompanyQuery;
import com.roamer.audition.common.response.CompanyVO;
import com.roamer.audition.common.service.CompanyService;
import com.roamer.audition.server.converter.CompanyConverter;
import com.roamer.audition.server.entity.AuditionRecord;
import com.roamer.audition.server.entity.Company;
import com.roamer.audition.server.query.CompanyPageQuerySpecification;
import com.roamer.audition.server.query.CompanyQuerySpecification;
import com.roamer.audition.server.repository.AuditionRecordRepository;
import com.roamer.audition.server.repository.CompanyRepository;
import com.roamer.rest.exception.suppert.DataNotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 公司 业务处理实现
 *
 * @author roamer
 * @version V1.0
 * @date 2019/9/2 8:23 下午
 */
@Slf4j
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class CompanyServiceImpl implements CompanyService {

    private final CompanyRepository companyRepository;
    private final AuditionRecordRepository auditionRecordRepository;
    private final CompanyConverter companyConverter;

    public CompanyServiceImpl(CompanyRepository companyRepository, AuditionRecordRepository auditionRecordRepository,
                              CompanyConverter companyConverter) {
        this.companyRepository = companyRepository;
        this.auditionRecordRepository = auditionRecordRepository;
        this.companyConverter = companyConverter;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ,
            rollbackFor = Exception.class)
    @Override
    public CompanyVO createCompany(CompanyDTO companyDTO) {
        Company company = companyConverter.dtoToEntity(companyDTO);
        company = companyRepository.save(company);
        return companyConverter.entityToVO(company);
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ,
            rollbackFor = Exception.class)
    @Override
    public List<CompanyVO> createCompany(Collection<CompanyDTO> companyDTOList) {
        List<Company> companyList = companyDTOList.stream()
                .map(companyConverter::dtoToEntity)
                .collect(Collectors.toList());
        companyRepository.saveAll(companyList);
        return companyList.stream().map(companyConverter::entityToVO).collect(Collectors.toList());
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ,
            rollbackFor = Exception.class)
    @Override
    public CompanyVO updateCompany(CompanyDTO companyDTO) throws DataNotFoundException {
        Optional<Company> companyOptional = companyRepository.findById(companyDTO.getId());
        companyOptional.orElseThrow(DataNotFoundException::new);
        companyConverter.copyNotNullPropertiesFromDTO(companyDTO, companyOptional.get());
        return companyConverter.entityToVO(companyOptional.get());
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ,
            rollbackFor = Exception.class)
    @Override
    public void deleteCompany(Long id) throws DataNotFoundException {
        Optional<Company> companyOptional = companyRepository.findById(id);
        companyOptional.orElseThrow(DataNotFoundException::new);
        // 先删除关联的面试计划
        Company company = companyOptional.get();
        List<AuditionRecord> auditionRecordList = company.getAuditionRecordList();
        auditionRecordRepository.logicDeleteAll(auditionRecordList);
        // 删除公司
        companyRepository.logicDelete(company);
    }

    @Override
    public CompanyVO getCompany(Long id) throws DataNotFoundException {
        Optional<Company> companyOptional = companyRepository.findById(id);
        companyOptional.orElseThrow(DataNotFoundException::new);
        return companyConverter.entityToVO(companyOptional.get());
    }

    @Override
    public Page<CompanyVO> getCompanyPage(CompanyPageQuery companyPageQuery) {
        CompanyPageQuerySpecification specification = companyConverter.pageQueryToSpecification(companyPageQuery);
        return companyRepository.findAll(specification.toSpec(), specification.toPageable())
                .map(companyConverter::entityToVO);
    }

    @Override
    public List<CompanyVO> getCompanyList(CompanyQuery companyQuery) {
        CompanyQuerySpecification specification = companyConverter.queryToSpecification(companyQuery);
        return companyRepository.findAll(specification.toSpec())
                .stream()
                .map(companyConverter::entityToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<CompanyVO> getCompanyList() {
        return companyRepository.findAll().stream().map(companyConverter::entityToVO).collect(Collectors.toList());
    }

    @Override
    public Long getAllCount() {
        return companyRepository.count();
    }

}
